use std::collections::HashMap;
use std::fmt::{Debug, Display};
use std::hash::Hash;
use std::slice::from_raw_parts;
use std::str::from_utf8_unchecked;

use crate::gen_title;

pub fn ch4_1_1() {
    gen_title("ch4_1_1", 18);

    #[derive(Debug)]
    struct Foo;

    impl Foo {
        fn mutate_and_share(&mut self) -> &Self {
            &*self
        }

        fn share(&self) {}
    }

    let mut foo = Foo;
    let loan = foo.mutate_and_share();
    println!("loan: {:?}", loan);
    foo.share();
}

pub fn ch4_1_2() {
    gen_title("ch4_1_2", 18);

    fn get_default<K, V>(map: &mut HashMap<K, V>, key: K) -> &V
    where
        K: Clone + Eq + Hash,
        V: Default,
    {
        match map.get(&key) {
            Some(_) => map.get(&key).unwrap(),
            None => {
                map.insert(key.clone(), V::default());
                map.get(&key).unwrap()
            }
        }
    }
    let mut map1 = HashMap::new();
    map1.insert("key", "value");
    get_default(&mut map1, "key");
    println!("{:?}", map1);
}

pub fn ch4_1_3() {
    gen_title("ch4_1_3", 18);

    fn fn_elision(x: &i32) -> &i32 {
        x
    }

    let closure_s: Box<dyn Fn(&i32) -> &i32> = Box::new(|x: &i32| -> &i32 { x });
    assert_eq!(*closure_s(&45), 45);
    println!("{}", closure_s(&45))
}

pub fn ch4_1_4() {
    gen_title("ch4_1_4", 18);

    let mut s = String::from("hello");

    let r1 = &s;
    let r2 = &s;
    println!("{} and {}", r1, r2);

    let r3 = &mut s;
    println!("{}", r3);
}

pub fn ch4_1_5() {
    gen_title("ch4_1_5", 18);

    #[derive(Debug)]
    struct Point {
        x: i32,
        y: i32,
    }

    impl Point {
        fn move_to(&mut self, x: i32, y: i32) {
            self.x = x;
            self.y = y;
        }
    }

    let mut p = Point { x: 0, y: 0 };
    let r = &mut p;
    let rr: &Point = &r;

    println!("{:?}", rr);
    r.move_to(10, 10);
    println!("{:?}", r);

    fn read_length(strings: &mut Vec<String>) -> usize {
        strings.len()
    }
}

pub fn ch4_1_6() {
    gen_title("ch4_1_6", 18);

    struct Interface<'a: 'b, 'b> {
        manager: &'b mut Manager<'a>,
    }

    impl<'a: 'b, 'b> Interface<'a, 'b> {
        pub fn noop(self) {
            println!("interface consumed");
        }
    }

    struct Manager<'a> {
        text: &'a str,
    }

    struct List<'a> {
        manager: Manager<'a>,
    }

    impl<'a> List<'a> {
        pub fn get_interface<'b>(&'b mut self) -> Interface<'a, 'b>
        where
            'a: 'b,
        {
            Interface {
                manager: &mut self.manager,
            }
        }
    }

    let mut list = List {
        manager: Manager { text: "hello" },
    };

    list.get_interface().noop();

    println!("Interface should be dropped here an the borrow released");

    use_list(&list);

    fn use_list(list: &List) {
        println!("{}", list.manager.text);
    }
}

pub fn ch4_1_7() {
    gen_title("ch4_1_7", 18);

    let mark_twain: &str = "Samuel Clemens";
    print_author(mark_twain);

    fn print_author(author: &'static str) {
        println!("{}", author);
    }
}

pub fn ch4_1_8() {
    gen_title("ch4_1_8", 18);

    let mark_twain = "Samuel Clemens";
    print(&mark_twain);

    fn print<T: Display + 'static>(message: &T) {
        println!("{}", message);
    }
}

pub fn ch4_1_9() {
    gen_title("ch4_1_9", 18);

    fn get_memory_location() -> (usize, usize) {
        let string = "hello world!";
        let pointer = string.as_ptr() as usize;
        let length = string.len();
        (pointer, length)
    }

    fn get_str_at_location(pointer: usize, length: usize) -> &'static str {
        unsafe { from_utf8_unchecked(from_raw_parts(pointer as *const u8, length)) }
    }

    let (pointer, length) = get_memory_location();
    let message = get_str_at_location(pointer, length);
    println!(
        "The {} bytes at 0x{:X} stored: {}",
        length, pointer, message
    );
}

pub fn ch4_1_10() {
    gen_title("ch4_1_10", 18);

    fn print_it<T: Debug + 'static>(input: &T) {
        println!("'static value passed in this: {:?}", input);
    }

    fn print_it1(input: impl Debug + 'static) {
        println!("'static value passed in is: {:?}", input);
    }

    let i = 5;

    print_it(&i);
    // print_it1(&i);
}

pub fn ch4_1_11() {
    gen_title("ch4_1_11", 18);

    let r1;
    let r2;
    {
        static STATIC_EXAMPLE: i32 = 42;
        r1 = &STATIC_EXAMPLE;
        let x = "&'static str";
        r2 = x;
    }

    println!("&'static i32: {}", r1);
    println!("&'static str: {}", r2);

    let r3: &str;

    {
        let s1 = "String".to_string();
        static_bound(&s1);

        r3 = &s1;
    }

    // println!("{}", r3);

    fn static_bound<T: Display + 'static>(t: &T) {
        println!("{}", t);
    }
}

pub fn ch4_1_12() {
    let static_string: &str = "";
    {
        let static_string = "I'm in read-only memory";
        println!("static_string: {}", static_string);

        // 当 `static_string` 超出作用域时，该引用不能再被使用，但是数据依然会存在于 binary 所占用的内存中
    }

    println!("static_string reference remains alive: {}", static_string);
}

pub fn ch4_1_pra_1() {
    gen_title("ch4_1_pra_1", 18);

    #[derive(Debug)]
    struct Ref<'a, T: 'a>(&'a T);

    fn print<T>(t: T)
    where
        T: Debug,
    {
        println!("`print`: t is {:?}", t);
    }

    fn print_ref<'a, T>(t: &'a T)
    where
        T: Debug + 'a,
    {
        println!("`print_ref`: t is {:?}", t);
    }

    let x = 8;
    let ref_x = Ref(&x);

    print_ref(&ref_x);
    print(ref_x);
}

pub fn ch4_1_pra_2() {
    gen_title("ch4_1_pra_2", 18);

    #[derive(Debug)]
    struct DoubleRef<'a: 'b, 'b, T> {
        r: &'b T,
        s: &'a T,
    }

    let double_ref = DoubleRef { r: &1, s: &2 };

    println!("{:?}", double_ref);
}

pub fn ch4_1_pra_3() {
    gen_title("ch4_1_pra_3", 18);

    struct ImportantExcerpt<'a> {
        part: &'a str,
    }

    impl<'a: 'b, 'b> ImportantExcerpt<'a> {
        fn announce_and_return_part(&'a self, announcement: &'b str) -> &'b str {
            println!("Attention please: {}", announcement);
            self.part
        }
    }

    let excerpt = ImportantExcerpt { part: "abcdefg" };

    println!("{}", excerpt.announce_and_return_part("hhahahaha"));

    println!("Success");
}

pub fn ch4_1_pra_4() {
    gen_title("ch4_1_pra_4", 18);

    fn f<'a: 'b, 'b>(x: &'a i32, mut y: &'b i32) {
        y = x;
        let r: &'b &'a i32 = &&0;
        println!("{}", r);
    }

    println!("Success");
}
